/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.edu.unal.ahnmodeler.view;

import co.edu.unal.ahnmodeler.main.App;
import co.edu.unal.ahnmodeler.util.RandomObjects;
import java.awt.Dimension;
import java.text.DecimalFormat;

/**
 * Clase principal que representa el contenedor principal de la aplicación. Permite visualizar el panel de controles, el contenedor del modelo, y la barra de estado.
 * @author raider
 */
public class MainFrame extends javax.swing.JFrame {
    
    private static MainFrame INSTANCE = null;
    
    /* Creador sincronizado para protegerse de posibles problemas  multi-hilo, otra prueba para evitar instanciación múltiple.*/
    private synchronized static void createInstance() {
        if (INSTANCE == null) { 
            INSTANCE = new MainFrame();
        }
    }
 
    /**
     * Permite obtener la instanciá de la clase que representa el contenedor principal de la aplicación.
     * @return Instancia del contenedor principal de la aplicación.
     */
    public static MainFrame getInstance() {
        createInstance();
        return INSTANCE;
    }
    
    private MainFrame() {
        System.out.println("Clase MainFrame");
        initComponents();
        setPreferredSize(new Dimension(1024, 600));
        setSize(new Dimension(1024, 600));
        pack();
        pModel = PModel.getInstance(); //Panel canvas (panel en el que se pinta la red)
        getContentPane().add(pModel, java.awt.BorderLayout.CENTER);
        sBar = StatusBar.getInstance();
        getContentPane().add(sBar, java.awt.BorderLayout.SOUTH);
        BStopSimu.setEnabled(false);
    }

    /**
     * Permite obtener la instancia de la clase que representa el contenedor del modelo de la red Ad-Hoc.
     * @return Instancia de la clase que representa el contenedor del modelo de la red Ad-Hoc.
     */
    public PModel getpModel() {
        return pModel;
    }

    /**
     * Permite obtener la instancia de la clase que representa el contenedor de la barra de estado de la aplicación.
     * @return Instancia de la clase que representa el contenedor de la barra de estado de la aplicación.
     */
    public StatusBar getsBar() {
        return sBar;
    }
    
    /**
     * Permite actualizar el valor del texto de la medida de desempeño de los paquetes enviados sobre los paquetes recibidos.
     * @param receivedPackages Nuevo valor del número de paquetes recibidos.
     * @param sentPackages Nuevo valor del número de paquetes enviados.
     */
    public void updatePackagesMeasurement(double receivedPackages,double sentPackages){
        String succesfulConnections=new DecimalFormat("#.###").format((sentPackages>0?receivedPackages/sentPackages:0)*100);
        TFPM1.setText(receivedPackages+" / "+sentPackages+" = "+succesfulConnections+"%");
        PButtons.repaint();
    }
    
    /**
     * Permite actualizar el valor del texto de la medida de desempeño del número promedio de saltos que hace un paquete.
     * @param newValue Nuevo valor del texto.
     */
    public void updateAvgJumps(double newValue){
        TFPM2.setText(new DecimalFormat("#.###").format(newValue));
        PButtons.repaint();
    }
    
    /**
     * Permite actualizar el valor del texto de la medida de desempeño del tiempo promedio que se demora un paquete en llegar a su destino.
     * @param newValue Nuevo valor del texto.
     */
    public void updateAvgTime(double newValue){
        TFPM3.setText(new DecimalFormat("#.###").format(newValue));
        PButtons.repaint();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        PButtons = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        BGenNetwork = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        SNumNodos = new javax.swing.JSpinner();
        CbNumNodAleat = new javax.swing.JCheckBox();
        jPanel2 = new javax.swing.JPanel();
        BAddNode = new javax.swing.JButton();
        BDeleteNode = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        BStartSimu = new javax.swing.JButton();
        BStopSimu = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();
        BResetNet = new javax.swing.JButton();
        jPanel4 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        TFPM1 = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        TFPM2 = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        TFPM3 = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Ad-Hoc Netowork Modeler - Universidad Nacional de Colombia");
        setResizable(false);

        PButtons.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Red"));

        BGenNetwork.setText("Generar Red");
        BGenNetwork.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BGenNetworkActionPerformed(evt);
            }
        });

        jLabel1.setText("Numero de Nodos:");

        SNumNodos.setModel(new javax.swing.SpinnerNumberModel(1, 1, 100, 1));

        CbNumNodAleat.setText("Numero de nodos aleatorio");
        CbNumNodAleat.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CbNumNodAleatActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addGap(18, 18, 18)
                        .addComponent(SNumNodos, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(BGenNetwork, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(CbNumNodAleat, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(SNumNodos, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(CbNumNodAleat)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(BGenNetwork)
                .addGap(19, 19, 19))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Modificar Red"));

        BAddNode.setText("Agregar Nodo");
        BAddNode.setEnabled(false);
        BAddNode.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BAddNodeActionPerformed(evt);
            }
        });

        BDeleteNode.setText("Eliminar Nodo");
        BDeleteNode.setEnabled(false);
        BDeleteNode.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BDeleteNodeActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGap(7, 7, 7)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(BDeleteNode, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(BAddNode, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(BAddNode)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(BDeleteNode))
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Contoles"));

        BStartSimu.setText("Iniciar Simulación");
        BStartSimu.setEnabled(false);
        BStartSimu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BStartSimuActionPerformed(evt);
            }
        });

        BStopSimu.setText("Terminar Simulación");
        BStopSimu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BStopSimuActionPerformed(evt);
            }
        });

        BResetNet.setText("Reiniciar Red");
        BResetNet.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BResetNetActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(BStartSimu, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(BStopSimu, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jSeparator1)
                    .addComponent(BResetNet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(BStartSimu)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(BStopSimu)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(BResetNet))
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Desempeño de Red"));

        jLabel2.setText("Paq. Entregados / Paq. Enviados:");

        TFPM1.setEditable(false);
        TFPM1.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        jLabel3.setText("Numero promedio de saltos:");

        TFPM2.setEditable(false);
        TFPM2.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        jLabel4.setText("Gasto de tiempo promedio:");

        TFPM3.setEditable(false);
        TFPM3.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(TFPM1)
                    .addComponent(jLabel3)
                    .addComponent(TFPM2)
                    .addComponent(jLabel4)
                    .addComponent(TFPM3))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(TFPM1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(TFPM2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel4)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(TFPM3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        javax.swing.GroupLayout PButtonsLayout = new javax.swing.GroupLayout(PButtons);
        PButtons.setLayout(PButtonsLayout);
        PButtonsLayout.setHorizontalGroup(
            PButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        PButtonsLayout.setVerticalGroup(
            PButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(PButtonsLayout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(13, 13, 13)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 106, Short.MAX_VALUE)
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        getContentPane().add(PButtons, java.awt.BorderLayout.WEST);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void BAddNodeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BAddNodeActionPerformed
        App.getNetController().addNode();
        App.setStatus("Nodos Agregado");
    }//GEN-LAST:event_BAddNodeActionPerformed

    private void BDeleteNodeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BDeleteNodeActionPerformed
        App.getNetController().deleteNode();
        App.setStatus("Nodo Eliminado");
    }//GEN-LAST:event_BDeleteNodeActionPerformed

    private void BGenNetworkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BGenNetworkActionPerformed
        int numNodos;
        if(CbNumNodAleat.isSelected()){
            numNodos = RandomObjects.randomNumNodes();
        }else{
            numNodos = (int)SNumNodos.getValue();
        }
        App.getNetController().genNetwork(numNodos);
        BGenNetwork.setEnabled(false);
        BStartSimu.setEnabled(true);
        BAddNode.setEnabled(true);
        BDeleteNode.setEnabled(true);
        App.setStatus("Listo: Haga clic en Iniciar Simulacion");
    }//GEN-LAST:event_BGenNetworkActionPerformed

    private void CbNumNodAleatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CbNumNodAleatActionPerformed
        SNumNodos.setEnabled(!CbNumNodAleat.isSelected());
    }//GEN-LAST:event_CbNumNodAleatActionPerformed

    private void BStartSimuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BStartSimuActionPerformed
        App.getNetController().startSimulation();
        App.setStatus("Simulando...");
        sBar.setRunning(true);
        Thread thread=new Thread(sBar);
        thread.start();
        BStartSimu.setEnabled(false);
        BStopSimu.setEnabled(true);
        BResetNet.setEnabled(false);
    }//GEN-LAST:event_BStartSimuActionPerformed

    private void BResetNetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BResetNetActionPerformed
        App.getNetController().deleteNetwork();
        BGenNetwork.setEnabled(true);
        App.setStatus("Listo: Genere una red");
    }//GEN-LAST:event_BResetNetActionPerformed

    private void BStopSimuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BStopSimuActionPerformed
        App.getNetController().stopSimulation();
        BStopSimu.setEnabled(false);
        BAddNode.setEnabled(false);
        BDeleteNode.setEnabled(false);
        BResetNet.setEnabled(true);
    }//GEN-LAST:event_BStopSimuActionPerformed
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton BAddNode;
    private javax.swing.JButton BDeleteNode;
    private javax.swing.JButton BGenNetwork;
    private javax.swing.JButton BResetNet;
    private javax.swing.JButton BStartSimu;
    private javax.swing.JButton BStopSimu;
    private javax.swing.JCheckBox CbNumNodAleat;
    private javax.swing.JPanel PButtons;
    private javax.swing.JSpinner SNumNodos;
    private javax.swing.JTextField TFPM1;
    private javax.swing.JTextField TFPM2;
    private javax.swing.JTextField TFPM3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JSeparator jSeparator1;
    // End of variables declaration//GEN-END:variables

    private PModel pModel;
    private StatusBar sBar;
}
